package io.itit.ecp.data;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import io.itit.ecp.admin.server.entity.CarbonSinkDataEntity;
import io.itit.ecp.admin.server.entity.CarbonSinkEntity;
import io.itit.ecp.admin.server.entity.CarbonSinkFactorEntity;
import io.itit.ecp.admin.server.service.ICarbonSinkDataService;
import io.itit.ecp.admin.server.service.ICarbonSinkFactorService;
import io.itit.ecp.admin.server.service.ICarbonSinkService;
import io.itit.grass.common.server.helper.ThreadPoolHelper;
import io.itit.grass.common.utils.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Slf4j
@Component
public class CarbonSinkDataGenerate {

    @Resource
    private ThreadPoolHelper threadPoolHelper;

    @Resource
    private ICarbonSinkDataService carbonSinkDataService;

    @Resource
    private ICarbonSinkFactorService carbonSinkFactorService;

    @Resource
    private ICarbonSinkService carbonSinkService;

    /**
     * 每15分钟执行一次
     */
    @Scheduled(cron = "0 0,15,30,45 * * * *")
    public void generate() {
        log.info(" ====== 自动生成碳汇数据开始 ====== ");
        this.generateCarbonSinkDataHistory();
    }

    public void generateCarbonSinkDataHistory() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime start = now.with(TemporalAdjusters.firstDayOfMonth()).toLocalDate().atTime(LocalTime.MIN);
        LocalDateTime end = now.with(TemporalAdjusters.lastDayOfMonth()).toLocalDate().atTime(LocalTime.MAX);
        List<CarbonSinkFactorEntity> sinkFactorEntities = carbonSinkFactorService.lambdaQuery()
                .ge(CarbonSinkFactorEntity::getSolidifyDate, start)
                .lt(CarbonSinkFactorEntity::getSolidifyDate, end)
                .list();
        if (!sinkFactorEntities.isEmpty()) {
            Set<String> sinkFactorIds = sinkFactorEntities.stream().map(CarbonSinkFactorEntity::getId).collect(Collectors.toSet());
            List<CarbonSinkEntity> sinkEntities = carbonSinkService.lambdaQuery()
                    .in(CarbonSinkEntity::getCarbonSinkId, sinkFactorIds)
                    .list();
            if (!sinkEntities.isEmpty()) {
                Date date = new Date();
                DateUtil.offset(date, DateField.SECOND, 0);
                DateUtil.offset(date, DateField.MINUTE, CommonUtils.getMinuteTimeQuarter(now));
                for (CarbonSinkEntity sinkEntity : sinkEntities) {
                    BigDecimal factor = sinkFactorEntities.stream()
                            .filter(item -> StringUtils.equals(item.getId(), sinkEntity.getCarbonSinkId()))
                            .findFirst()
                            .map(CarbonSinkFactorEntity::getFactor).orElse(BigDecimal.ZERO);
                    CarbonSinkDataEntity dataEntity = new CarbonSinkDataEntity();
                    dataEntity.setCarbonSinkId(sinkEntity.getCarbonSinkId());
                    dataEntity.setSolidifyDate(date);
                    dataEntity.setSceneProjectId(sinkEntity.getSceneProjectId());
                    dataEntity.setSceneEdificeId(sinkEntity.getSceneEdificeId());
                    dataEntity.setSceneFloorId(sinkEntity.getSceneFloorId());
                    dataEntity.setSceneRoomId(sinkEntity.getSceneRoomId());
                    dataEntity.setCarbonSinkId(sinkEntity.getCarbonSinkId());
                    dataEntity.setType(sinkEntity.getId());
                    dataEntity.setSinkType("1");
                    dataEntity.setArea(sinkEntity.getArea());
                    setCarbonEmission(dataEntity, factor);
                    carbonSinkDataService.save(dataEntity);
                }
            }
        }
        log.info(" ====== 自动生成碳汇数据完成 ====== ");
    }

    private void setCarbonEmission(CarbonSinkDataEntity dataEntity, BigDecimal factor) {
        BigDecimal area = dataEntity.getArea();
        BigDecimal val = new BigDecimal("365").multiply(new BigDecimal("24")).multiply(new BigDecimal("4"));
        dataEntity.setArea(area.multiply(factor).divide(val, 2, RoundingMode.HALF_UP));
        dataEntity.setCarbonEmissionProcess(area.toPlainString() + "*" + factor.toPlainString() + "/365/24/4");
    }
}
